<!-- 实时推送 -->

<template>
  <div v-show="false" />
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import ROUTE from './ROUTE'

const TYPE = {
  alarmAddMsg: 'alarm', // 告警
  workOrderAddMsg: 'repair', // 维修
  work_order_workNotify: 'repairApp', // 移动端维修
  addWorkOrderMsg: 'repairApp', // 移动端维修(告警配置为工单通知时)
  plan_task_workNotify: 'taskApp', // 移动端任务
}

// 检查是否有个人工作台
const checkWorkbench = () => CORE.ROUTE.NAME_PASS.includes('WorkbenchPersonal')
// 检查是否为全部范围
const checkAllScope = (type) => {
  return ROUTE[type].some(([route, scope]) => !scope && CORE.MENU.ROUTE[route])
}
// 获取有权限的范围列表
const getScopeList = (type) => {
  const matched = ROUTE[type].filter(([route, scope]) => scope && CORE.MENU.ROUTE[route])
  return matched.map(([, scope]) => scope)
}

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name: 'Socket',

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    const NOTICE = { close: () => null } // 通知实例
    return {
      alarm: NOTICE,
      repair: NOTICE,
      repairApp: NOTICE,
      taskApp: NOTICE,
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 不通知的页面列表
     */
    NO_NOTICE: () => ['Home'],

    /**
     * 是否有告警通知
     */
    hasAlarm() {
      return checkAllScope('alarm') // 统一的实时告警页面
    },

    /**
     * 是否有维修工单
     */
    hasRepair() {
      return checkAllScope('repair') // 统一的维修工单页面
    },

    /**
     * 是否有移动端维修工单
     */
    hasRepairApp() {
      return checkAllScope('repairApp') || checkWorkbench() // 统一的移动端维修工单页面
    },

    /**
     * 是否有移动端任务通知
     */
    hasTaskApp() {
      return checkAllScope('taskApp') || checkWorkbench() // 统一的移动端任务记录页面
    },

    /**
     * 告警范围列表
     */
    alarmScopeList() {
      return getScopeList('alarm') // 独立的分组告警页面
    },

    /**
     * 维修范围列表
     */
    repairScopeList() {
      return getScopeList('repair') // 独立的分类工单页面
    },

    /**
     * 移动端维修范围列表
     */
    repairAppScopeList() {
      return getScopeList('repairApp') // 独立的移动端分类工单页面
    },

    /**
     * 移动端任务范围列表
     */
    taskAppScopeList() {
      return getScopeList('taskApp') // 独立的移动端分类任务页面
    },

    /**
     * 区域 ID 列表
     */
    areaIdList() {
      return Object.keys(CORE.REGION.MY_MAP)
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: {
    /**
     * 监听最新推送数据
     */
    'CORE.SOCKET.data'({ content, attachData }) {
      const obj = { ...attachData, content }
      this.checkMessage(obj) && this.alertMessage(obj) // 判断是否为通知
    },
  },

  /**
   * 创建完成 (先抽取再调用)
   */
  created() {
    CORE.socketConnect()
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 检查消息
     */
    checkMessage(obj) {
      const type = TYPE[obj.msgType]
      const noNotice = this.NO_NOTICE.includes(this.$route.name)
      if (!type || noNotice) return false

      const SCOPE = {
        alarm: obj.subSystemCode,
        repair: obj.orderTypeCode,
        repairApp: obj.orderTypeCode,
        taskApp: obj.planType,
      }
      const hasType = this[CORE.keyPre(type, 'has')] || this[`${type}ScopeList`].includes(SCOPE[type])
      const hasAreaId = CORE.USER.isAdmin || !obj.areaId || this.areaIdList.includes(obj.areaId)

      switch (type) {
        case 'alarm': return hasType && hasAreaId
        case 'repair': return hasType
        case 'repairApp': return hasType
        case 'taskApp': return hasType
        default: return false
      }
    },

    /**
     * 弹出消息
     */
    alertMessage({ msgType, id, title, content }) {
      const type = TYPE[msgType]

      // 点击详情
      const click = () => {
        this[type].close()
        CORE[CORE.keyPre(type, 'openDetail')](id)
      }

      // 消息内容
      const h = this.$createElement
      const text = h('span', content)
      const btn = h('el-button', { props: { size: 'mini' }, style: { float: 'right' }, on: { click } }, '详情')

      // 打开通知
      this[type].close()
      this[type] = this.$notify({
        title,
        message: h('div', [text, btn]),
        duration: 0,
        dangerouslyUseHTMLString: true,
        type: 'warning',
        position: 'bottom-right',
        customClass: 'Socket-Notification',
      })
    },
  },
}
</script>

<style lang="scss">
@import './index.scss';
</style>
